# -*- coding: utf-8 -*-

'''
/**
 * @addtogroup FileSysOpt
 * FileSysOpt
 * @{
 */
/**
 * @file        FileSysOpt.py
 * @brief       ZipOpt.py正式更名为 FileSysOpt.py
 * @note        XXXX
 * @author      靳普诏(puzhao.jin@hopechart.com)
 * @date        2023/08/31
 * @version     1.0

 * @par         修改日志
 * <table>
 * <tr><th>Date         <th>Version     <th>Author      <th> Description
 * <tr><td>2023/08/31   <td>1.0         <td>靳普诏       <td> 创建初始版本
 * <tr><td>2024/01/05   <td>2.0         <td>靳普诏       <td> 文件更名为 FileSysOpt.py
 * @copyright   xxxx
 */
'''

import sys
import os
import zipfile
import shutil
import hashlib
from typing import Final

from functools import cmp_to_key


##----------------------------------------------------------------------------------------------------------

def TypedefFunction_ListComp(x, y) ->int:
    # 自定义比较函数
    if x < y:
        return -1
    elif x > y:
        return 1
    else:
        return 0

def ListSort(user_list: list, compare_func: TypedefFunction_ListComp=None, reverse: bool = False) -> list:
    """
    对列表进行排序。
    
    :param user_list: 待排序的列表
    :param compare_func: 比较函数，默认为 None
    :param reverse: 是否逆序排序，默认为 False
    :return: 排序后的列表
    """
    if compare_func is not None:
        # 将比较函数转换为关键字函数
        key = cmp_to_key(compare_func)
    else:
        key = None
    
    return sorted(user_list, key=key, reverse=reverse)


def ListFiles(path: str, show_log: bool = True, recursive: bool = False) -> list:
    """
    列出指定目录下的所有文件。
    
    :param path: 目录路径
    :param show_log: 是否显示日志，默认为 True
    :param recursive: 是否递归遍历，默认为 False
    :return: 文件路径列表
    """
    file_list = []
    
    # 如果需要递归遍历
    if recursive:
        for root, dirs, files in os.walk(path):
            for file in files:
                file_list.append(os.path.join(root, file))
                if show_log:
                    print(file)
    else:
        # 如果不需要递归遍历，则只处理当前目录
        with os.scandir(path) as entries:
            for entry in entries:
                if entry.is_file():
                    file_list.append(entry.path)
                    if show_log:
                        print(entry.name)
    return file_list


def ListDirs(path: str, show_log: bool = True) -> list:
    """
    列出指定目录下的所有目录。
    """
    dir_list = []
    for root, dirs, files in os.walk(path):
        for dir in dirs:
            dir_list.append(os.path.join(root, dir))
            if show_log:
                print(os.path.join(root, dir))
    return dir_list


##----------------------------------------------------------------------------------

def ValidateFilePath(filename: str) -> bool:
    """
    验证文件路径是否安全。简单示例仅检查是否为绝对路径且是否指向预期目录。
    根据实际需求，这里的验证可以更加严格和详细。
    """
    return os.path.isabs(filename)

def DirnameOfTheFile(filename: str) -> str:
    """
    返回给定文件名的目录部分。
    
    参数:
    filename (str): 完整的文件路径。
    
    返回:
    str: 文件所在的目录路径。
    """
    return os.path.dirname(os.path.abspath(filename))


def FileBasename(path):  
    ''' 
    @brief 获取文件的基础名称
        根据传入的文件路径，提取并返回文件的基础名称。
    @param path: str
        需要获取基础名称的文件路径。
    @return: str
        返回文件的基础名称。
    '''
    return os.path.basename(path)

##------------------------------------------------------------------

def CopyFile(source_filename: str, dest_filename: str, show_log: bool = True):
    """
    将源文件复制到目标文件。
    
    参数:
        source_filename (str): 源文件的路径。
        dest_filename (str): 目标文件的路径。
        
    异常:
        FileNotFoundError: 如果源文件不存在。
        ValueError: 如果目标文件位于源文件的目录内。
        Exception: 在文件操作过程中遇到其他错误。
    """
    
    # 验证源文件
    if not os.path.isfile(source_filename):
        raise FileNotFoundError(f"源文件 {source_filename} 不存在。")
    
    # 验证并准备目标文件路径
    if os.path.commonprefix([source_filename, dest_filename]) == source_filename:
        raise ValueError("目标文件路径位于源文件路径的目录内，不安全。")
    
    # 进行文件复制并处理异常
    try:
        with open(source_filename, 'rb') as r_f:
            with open(dest_filename, 'wb') as w_f:
                # 改进的复制大文件的方法
                buffer_size = 4096  # 4KB 缓冲区
                while True:
                    chunk = r_f.read(buffer_size)
                    if not chunk:
                        break
                    w_f.write(chunk)
        if show_log:
            print(f"文件 {source_filename} 已复制到 {dest_filename}。")
    except Exception as e:
        # 可以进一步细化以处理特定异常
        raise Exception(f"在复制文件时发生错误: {str(e)}")



def CopyFolder(src: str, dst: str, show_log: bool = True) -> None:  
    """
    递归地将一个文件夹复制到另一个指定的文件夹路径，并打印复制过程。
    
    :param src: 源文件夹路径。
    :param dst: 目标文件夹路径。
    :return: None
    """
    # 确保目标目录不存在，如果存在则删除
    if os.path.exists(dst):
        shutil.rmtree(dst)
    
    # 创建目标目录
    os.makedirs(dst, exist_ok=True)
    print(f"CopyFolder '{src}' '{dst}'")
    
    for root, dirs, files in os.walk(src):
        # 复制子目录
        for dir_name in dirs:
            src_dir = os.path.join(root, dir_name)
            dst_dir = src_dir.replace(src, dst)
            os.makedirs(dst_dir, exist_ok=True)
            if show_log:
                print(f"Creating directory: {dst_dir}")
        
        # 复制文件
        for file_name in files:
            src_file = os.path.join(root, file_name)
            dst_file = src_file.replace(src, dst)
            shutil.copy2(src_file, dst_file)
            if show_log:
                print(f"Copying file: {src_file} -> {dst_file}")



##-------------------------------------------------------------------------------------

def SearchFilesExt(startpath, extension = None):
    """
    搜索指定目录下的带有指定扩展名的文件，并将这些文件的相对路径存储在一个列表中。

    参数:
    startpath (str): 起始目录路径，即从该目录开始搜索
    extension (str): 指定扩展名，例如 ".txt"

    返回:
    list: 包含搜索到的文件的相对路径的列表

    注意:
    1. 这段代码使用了`os`模块，因此需要在Python代码中导入`os`模块。
    2. 请确保传入的`startpath`是一个正确的目录路径，否则可能会导致遍历错误。
    3. 请确保传入的`extension`是一个正确的扩展名，否则可能不会搜索到任何文件。
    4. 这段代码会递归地搜索子目录中的文件，如果子目录太多，可能会导致性能问题。

    示例:
    >>> startpath = "/path/to/your/directory"
    >>> extension = ".txt"
    >>> files_with_extension = search_files_with_extension(startpath, extension)
    >>> print(files_with_extension)
    ['path/to/your/directory/file1.txt', 'path/to/your/directory/file2.txt', 'path/to/your/directory/subdirectory/file3.txt']
    """
    file_list = []

    for root, dirs, files in os.walk(startpath):
        for file in files:
            if extension == None or file.endswith(extension):
                filename = os.path.relpath(os.path.join(root, file), startpath)
                file_list.append(filename)
    print(file_list)
    return file_list



